package com.hair.logy.core.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class QRcodeUtil {
    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 300;


    private static final String BASE_PATH = "";

    /**
     * 生成二维码图片
     * @param url 扫描二维码跳转地址
     * @return
     * @throws Exception
     */
    public static BufferedImage createImage(String url) throws Exception {
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
                hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

    /**
     * 输出二维码
     * @param url 扫描二维码跳转地址
     * @param response
     * @throws Exception
     */
    public static void encode(String url, HttpServletResponse response)
            throws Exception {
        BufferedImage image = createImage(url);
        ImageIO.write(image, FORMAT_NAME, response.getOutputStream());


    }
    public static void encodeWithLogo(String url, HttpServletResponse response)
            throws Exception {
        BufferedImage image = createImageWithLogo(url,BASE_PATH);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, FORMAT_NAME, outputStream);

    }
    /**
     * 给二维码插入logo图片
     * @param image
     * @param logoPath
     * @return
     */
    public static BufferedImage insertLogo(BufferedImage image, InputStream logoPath) {

        try {
            BufferedImage logo = ImageIO.read(logoPath);
            int width = logo.getWidth();
            int height = logo.getHeight();
            if (width > 100) {
                width = 100;
            }
            if (height > 100) {
                height = 100;
            }
            //压缩Logo
            Image logoTemp = logo.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage bfImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            //获取画布
            Graphics graphics = bfImage.getGraphics();
            //画logoTemp
            graphics.drawImage(logoTemp, 0, 0, null);
            graphics.dispose();
            //获取原二维码
            Graphics2D graphicsQRCode = image.createGraphics();
            //logo插入二维码,定义位置x,y 中间位置
            int x = (image.getWidth() - width) / 2;
            int y = (image.getHeight() - height) / 2;
            //压缩后的logo画进二维码
            graphicsQRCode.drawImage(logoTemp, x, y, null);
            //logo的四个角圆滑  两个6定义弧度
            Shape shape = new RoundRectangle2D.Float(x, y, width, height, 6, 6);
            //设置画笔的粗细
            graphicsQRCode.setStroke(new BasicStroke(3f));
            //画到画布
            graphicsQRCode.draw(shape);
            //释放资源
            graphicsQRCode.dispose();
        } catch ( IOException e) {
            e.printStackTrace();
        }
        return image;
    }
    /**
     * 生成带logo的二维码
     * @param
     * @return
     */
    public static BufferedImage createImageWithLogo( String url, String  path)  {




        HashMap map = new HashMap();
        //设置容错等级
        map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //定义字符集，我们设置为utf-8
        map.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //设置边距，二维码边距空白宽度为0
        map.put(EncodeHintType.MARGIN, 2);
        BufferedImage image = null;
        try {
            File  logoPath=new File(path) ;


            FileInputStream   fileInputStream=new FileInputStream(logoPath);
            //生成二维码对象
            BitMatrix bitMatrix = new MultiFormatWriter()
                    .encode(url, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, map);
            image = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < QRCODE_SIZE; x++) {
                for (int y = 0; y < QRCODE_SIZE; y++) {
                    image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0XFFFFFFFF);
                }
            }
            if(!StringUtils.isEmpty(logoPath)){
                   insertLogo(image,fileInputStream);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return image;
    }

    public static void main(String[] args) {
        java.util.List<String> contents = new ArrayList<>();
        contents.add("http://www.example.com/page1");
        contents.add("http://www.example.com/page2");
        contents.add("http://www.example.com/page3");
        //generateQrCodes(contents, "qr_code", "png");
    }



    // 批量生成文件
    public static java.util.List<File> generateQrCodes(java.util.List<String> contents, Map<String ,String> contentMaps, String format) {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        int size = 300;
        java.util.List<File>  files=new ArrayList<>();
        for (int i = 0; i < contents.size(); i++) {
            String content = contents.get(i);
            BitMatrix bitMatrix;
            try {
                bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, size, size,
                        generateHintMap());
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }

            String  cardNo=  contentMaps.get(content);
            BufferedImage bufferedImage = bitMatrixToImage(bitMatrix);
            String fileName = cardNo + "." + format;
            File file=  saveImage(bufferedImage, fileName, format);
            files.add(file);
        }
        return  files;
    }

    private static BufferedImage bitMatrixToImage(BitMatrix bitMatrix) {
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

    private static File saveImage(BufferedImage image, String fileName, String format) {
        File  file= new File(fileName);
        try {
            ImageIO.write(image, format, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    private static java.util.List<BarcodeFormat> getSupportedFormats() {
        java.util.List<BarcodeFormat> formats = new ArrayList<>();
        formats.add(BarcodeFormat.QR_CODE);
        return formats;
    }

    private static java.util.Map<EncodeHintType, Object> generateHintMap() {
        java.util.Map<EncodeHintType, Object> hints = new java.util.EnumMap<>(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 2);
        hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
        return hints;
    }


}
